package com.schedule.schedule.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.schedule.exception_advice.BusinessException;
import com.schedule.exception_advice.BusinessExceptionEnum;
import com.schedule.schedule.entity.ListParm;
import com.schedule.schedule.entity.ScheduleCourse;
import com.schedule.schedule.entity.ScheduleCourseListVo;
import com.schedule.schedule.entity.ScheduleParm;
import com.schedule.schedule.mapper.ScheduleCourseMapper;
import com.schedule.schedule.service.ScheduleCourseService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class ScheduleCourseServiceImpl extends ServiceImpl<ScheduleCourseMapper, ScheduleCourse> implements ScheduleCourseService {
    @Override
    public void saveSchedule(ScheduleParm scheduleParm) {
        //获取星期
        List<Integer> weekList = scheduleParm.getWeeks();
        LocalDate startDate = scheduleParm.getStartDate();
        LocalDate endDate = scheduleParm.getEndDate();
        List<LocalDate> dateList = new ArrayList<>();
        while(startDate.compareTo(endDate) <=0){
            //获取所有的时间
            if(weekList.contains(startDate.getDayOfWeek().getValue())){
                dateList.add(startDate);
            }
            startDate = startDate.plusDays(1);
        }
        //从数据库查询教室时间是否冲突
        List<ScheduleCourseListVo> roomList =  this.baseMapper.getScheduleList(
                Wrappers.query()
                        .eq("cs.room_id",scheduleParm.getRoomId())
                        .in("cs.date_time",dateList)
                        .orderByAsc("cs.date_time,cs.begin_time")
        );
        //处理占用信息
        Set<String> errorSet = new HashSet<>();
        for (ScheduleCourseListVo vo : roomList) {
            if (timeHasUsed(scheduleParm.getBeginTime(), scheduleParm.getEndTime(), vo.getBeginTime(), vo.getEndTime())) {
                errorSet.add(String.format("%s %s-%s %s %s %s", vo.getDateTime(), vo.getBeginTime(), vo.getEndTime(),
                        vo.getRoomName(), vo.getCourseName(), vo.getTeacherName()));
            }
        }
        //教师冲突的查询
        List<ScheduleCourseListVo> teacherVoList =  this.baseMapper.getScheduleList(Wrappers.query()
        .eq("cs.teacher_id",scheduleParm.getTeacherId())
        .in("cs.date_time",dateList)
        .orderByAsc("cs.date_time,cs.begin_time")
        );
        //处理占用信息
        for (ScheduleCourseListVo vo : teacherVoList) {
            if (timeHasUsed(scheduleParm.getBeginTime(), scheduleParm.getEndTime(), vo.getBeginTime(),
                    vo.getEndTime())) {
                errorSet.add(String.format("%s %s-%s %s %s %s", vo.getDateTime(), vo.getBeginTime(), vo.getEndTime(),
                        vo.getRoomName(), vo.getCourseName(), vo.getTeacherName()));
            }
        }
        //如果时间冲突
        if (errorSet.size() > 0) {
            throw new BusinessException(BusinessExceptionEnum.SCHEDULE_ERROR.getCode(), errorSet.toString());
        }
        //排课入库处理
        List<ScheduleCourse> list = new ArrayList<>();
        for(LocalDate date : dateList){
            ScheduleCourse schedule = new ScheduleCourse();
            schedule.setDateTime(date);
            schedule.setDuration(scheduleParm.getDuration());
            schedule.setTeacherId(scheduleParm.getTeacherId());
            schedule.setCourseId(scheduleParm.getCourseId());
            schedule.setRoomId(scheduleParm.getRoomId());
            schedule.setBeginTime(scheduleParm.getBeginTime());
            schedule.setEndTime(scheduleParm.getEndTime());
            list.add(schedule);
        }
        //保存
        this.saveBatch(list);
    }

    @Override
    public List<ScheduleCourse> selectCourseSchedulingList(ListParm query) {
        //条件构造器
       QueryWrapper<ScheduleCourse> queryWrapper = new QueryWrapper<>();
       queryWrapper.lambda().in(query.getRoomIdList() != null && query.getRoomIdList().size() > 0,ScheduleCourse::getRoomId)
               .in(query.getCourseIdList() != null && query.getCourseIdList().size() > 0,ScheduleCourse::getCourseId)
                .in(query.getTeacherIdList() != null && query.getTeacherIdList().size() > 0,ScheduleCourse::getTeacherId)
                .ge(StringUtils.isNotEmpty(query.getStartDate()), ScheduleCourse::getDateTime, query.getStartDate())
                .le(StringUtils.isNotEmpty(query.getEndDate()), ScheduleCourse::getDateTime, query.getEndDate())
                .eq(StringUtils.isNotEmpty(query.getBeginTime()), ScheduleCourse::getBeginTime, query.getBeginTime())
                .eq(StringUtils.isNotEmpty(query.getEndTime()), ScheduleCourse::getEndTime, query.getEndTime());
        return this.baseMapper.selectCourseSchedulingList(queryWrapper);
    }

    //时间转为分钟
    private Integer toMinute(LocalTime time) {
        return time.getHour() * 60 + time.getMinute();
    }

    private boolean isBetween(LocalTime time, LocalTime destTime1, LocalTime destTime2) {
        Integer minute = toMinute(time);
        return toMinute(destTime1) < minute && minute < toMinute(destTime2);
    }
    // 判断时间是否冲突
    private boolean timeHasUsed(LocalTime beginTime, LocalTime endTime, LocalTime dbBeginTime,
                            LocalTime dbEndTime) {
        return isBetween(beginTime, dbBeginTime, dbEndTime)
                || isBetween(endTime, dbBeginTime, dbEndTime)
                || isBetween(dbBeginTime, beginTime, endTime)
                || isBetween(dbEndTime, beginTime, endTime)
                || (beginTime.equals(dbBeginTime) && endTime.equals(dbEndTime));
    }
}
